// ============================================
// 14 - 自动化测试 (Automated Testing)
// ============================================

/// Rust 内置了测试框架，可以编写和运行测试

// ==================== 测试基础 ====================

/// 测试函数基础
/// 使用 #[test] 属性标记测试函数
pub fn testing_basics() {
    println!("\n=== 测试基础 ===");
    println!("使用 cargo test 运行测试");
    println!("测试函数使用 #[test] 属性标记");
    println!("测试可以包含断言");
}

/// 简单的被测试函数
pub fn add_two(a: i32) -> i32 {
    a + 2
}

pub fn greeting(name: &str) -> String {
    format!("你好，{}!", name)
}

// ==================== 断言宏 ====================

/// 断言宏
pub fn assertion_macros() {
    println!("\n=== 断言宏 ===");
    
    println!("常用断言宏:");
    println!("1. assert!() - 断言条件为真");
    println!("2. assert_eq!() - 断言两值相等");
    println!("3. assert_ne!() - 断言两值不等");
}

#[derive(Debug, PartialEq)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

// ==================== 自定义失败消息 ====================

/// 自定义失败消息
pub fn custom_failure_messages() {
    println!("\n=== 自定义失败消息 ===");
    println!("可以在断言后添加自定义消息");
    println!("assert!(condition, \"错误信息: {{}}\", value);");
}

// ==================== should_panic 测试 ====================

/// 测试 panic
pub fn testing_panics() {
    println!("\n=== 测试 Panic ===");
    println!("使用 #[should_panic] 测试代码是否会 panic");
}

pub struct Guess {
    value: i32,
}

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess 值必须在 1 到 100 之间，得到 {}", value);
        }
        
        Guess { value }
    }
}

// ==================== Result<T, E> 测试 ====================

/// 使用 Result 的测试
pub fn result_in_tests() {
    println!("\n=== Result 测试 ===");
    println!("测试函数可以返回 Result<(), E>");
    println!("使用 ? 运算符简化错误处理");
}

// ==================== 控制测试运行 ====================

/// 控制测试运行
pub fn controlling_test_runs() {
    println!("\n=== 控制测试运行 ===");
    
    println!("常用选项:");
    println!("cargo test -- --test-threads=1  # 串行运行");
    println!("cargo test -- --show-output     # 显示输出");
    println!("cargo test test_name            # 运行特定测试");
    println!("cargo test module_name          # 运行模块测试");
}

/// 测试组织
pub fn test_organization() {
    println!("\n=== 测试组织 ===");
    
    println!("测试类型:");
    println!("1. 单元测试 - 测试单个模块");
    println!("2. 集成测试 - 测试库的公共 API");
    println!("3. 文档测试 - 测试文档中的代码示例");
}

// ==================== 忽略测试 ====================

/// 忽略某些测试
pub fn ignoring_tests() {
    println!("\n=== 忽略测试 ===");
    println!("使用 #[ignore] 属性忽略测试");
    println!("cargo test -- --ignored  # 只运行被忽略的测试");
    println!("cargo test -- --include-ignored  # 运行所有测试");
}

// ==================== 测试私有函数 ====================

/// 测试私有函数
fn internal_adder(a: i32, b: i32) -> i32 {
    a + b
}

pub fn testing_private_functions() {
    println!("\n=== 测试私有函数 ===");
    println!("Rust 允许测试私有函数");
    println!("测试模块可以访问父模块的私有项");
}

// ==================== 基准测试 ====================

/// 基准测试
pub fn benchmark_tests() {
    println!("\n=== 基准测试 ===");
    println!("使用 #[bench] 进行性能测试（需要 nightly）");
    println!("或使用 criterion crate 进行基准测试");
}

// ==================== 测试最佳实践 ====================

/// 测试最佳实践
pub fn test_best_practices() {
    println!("\n=== 测试最佳实践 ===");
    
    println!("1. 每个函数至少有一个测试");
    println!("2. 测试边界条件和错误情况");
    println!("3. 使用描述性的测试名称");
    println!("4. 保持测试简单和独立");
    println!("5. 使用 assert_eq! 而不是 assert!");
    println!("6. 为测试添加有用的错误消息");
    println!("7. 定期运行测试");
}

// ==================== 测试驱动开发 ====================

/// 测试驱动开发 (TDD)
pub fn test_driven_development() {
    println!("\n=== 测试驱动开发 ===");
    
    println!("TDD 流程:");
    println!("1. 编写失败的测试");
    println!("2. 编写最少的代码使测试通过");
    println!("3. 重构代码");
    println!("4. 重复以上步骤");
}

// ==================== Mock 和 Stub ====================

/// Mock 和 Stub
pub fn mocking_and_stubbing() {
    println!("\n=== Mock 和 Stub ===");
    println!("使用 mockall crate 进行 mock");
    println!("使用 trait 实现依赖注入");
}

// 示例: 可测试的设计
pub trait MessageSender {
    fn send(&self, message: &str) -> Result<(), String>;
}

pub struct EmailSender;

impl MessageSender for EmailSender {
    fn send(&self, message: &str) -> Result<(), String> {
        // 实际发送邮件的代码
        println!("发送邮件: {}", message);
        Ok(())
    }
}

pub struct MockSender {
    pub messages: std::cell::RefCell<Vec<String>>,
}

impl MessageSender for MockSender {
    fn send(&self, message: &str) -> Result<(), String> {
        self.messages.borrow_mut().push(message.to_string());
        Ok(())
    }
}

pub fn notify_user<T: MessageSender>(sender: &T, user: &str, message: &str) {
    let full_message = format!("致 {}: {}", user, message);
    let _ = sender.send(&full_message);
}

// ==================== 主函数 ====================

/// 主函数 - 演示所有功能
#[allow(dead_code)]
pub fn main() {
    println!("╔════════════════════════════════════════╗");
    println!("║   Rust 自动化测试教程                  ║");
    println!("╚════════════════════════════════════════╝");
    
    testing_basics();
    assertion_macros();
    custom_failure_messages();
    testing_panics();
    result_in_tests();
    controlling_test_runs();
    test_organization();
    ignoring_tests();
    testing_private_functions();
    benchmark_tests();
    test_best_practices();
    test_driven_development();
    mocking_and_stubbing();
    
    println!("\n✅ 自动化测试教程完成！");
}

// ==================== 测试模块 ====================

#[cfg(test)]
mod tests {
    use super::*;
    
    // 基本测试
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
    
    #[test]
    fn test_add_two() {
        assert_eq!(add_two(2), 4);
        assert_eq!(add_two(10), 12);
    }
    
    // 测试 Rectangle
    #[test]
    fn larger_can_hold_smaller() {
        let larger = Rectangle {
            width: 8,
            height: 7,
        };
        let smaller = Rectangle {
            width: 5,
            height: 1,
        };
        
        assert!(larger.can_hold(&smaller));
    }
    
    #[test]
    fn smaller_cannot_hold_larger() {
        let larger = Rectangle {
            width: 8,
            height: 7,
        };
        let smaller = Rectangle {
            width: 5,
            height: 1,
        };
        
        assert!(!smaller.can_hold(&larger));
    }
    
    // 测试字符串
    #[test]
    fn greeting_contains_name() {
        let result = greeting("小明");
        assert!(
            result.contains("小明"),
            "问候语不包含名字，结果是 `{}`",
            result
        );
    }
    
    // 测试 panic
    #[test]
    #[should_panic(expected = "值必须在 1 到 100 之间")]
    fn greater_than_100() {
        Guess::new(200);
    }
    
    // 使用 Result 的测试
    #[test]
    fn it_works_with_result() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("2 + 2 不等于 4"))
        }
    }
    
    // 测试私有函数
    #[test]
    fn internal() {
        assert_eq!(internal_adder(2, 2), 4);
    }
    
    // 忽略的测试
    #[test]
    #[ignore]
    fn expensive_test() {
        // 耗时的测试代码
        assert_eq!(2 + 2, 4);
    }
    
    // 测试 mock
    #[test]
    fn test_notify_user() {
        let mock_sender = MockSender {
            messages: std::cell::RefCell::new(Vec::new()),
        };
        
        notify_user(&mock_sender, "张三", "测试消息");
        
        let messages = mock_sender.messages.borrow();
        assert_eq!(messages.len(), 1);
        assert!(messages[0].contains("张三"));
        assert!(messages[0].contains("测试消息"));
    }
    
    // 多个断言
    #[test]
    fn multiple_assertions() {
        let rect = Rectangle {
            width: 10,
            height: 20,
        };
        
        assert_eq!(rect.width, 10);
        assert_eq!(rect.height, 20);
        assert_ne!(rect.width, rect.height);
    }
}

